#include 	"logger.h"
#include	"w25qxx.h"
#include 	"rtc.h"
#include	"command.h"
#include	"short_test.h"
#include  "usart.h"

uint16_t	AdrRamLog;
uint16_t	AdrLogCount;
uint8_t		RamLogger[W25QXX_SECTOR_LENGTH];
uint32_t	LogCountIdx = 0x55555555;
uint32_t	LogLengthIdx = 0x55555555;

void LoggerIni(void)
{
    uint16_t	i;

    if(Readu32DatFrom_FlashMCUReg(FLASH_LOG_COUNT_IDX) != LogCountIdx)				//first used
    {
        Writeu32DatTo_FlashMCUReg(&LogCountIdx,1,FLASH_LOG_COUNT_IDX);
        W25QXX_Erase_Sector(FLASH_LOG_COUNT_ADR/W25QXX_SECTOR_LENGTH);
    }
    W25QXX_Read(RamLoggerCount,FLASH_LOG_COUNT_ADR,W25QXX_SECTOR_LENGTH);

    for(i = 0; i < W25QXX_SECTOR_LENGTH ; i++) 																//get the adr of the count reg
    {
        if(RamLoggerCount[i] == 0xff)
        {
            break;
        }
    }
    if(i)
    {
        if(i == W25QXX_SECTOR_LENGTH)
        {
            AdrLogCount = W25QXX_SECTOR_LENGTH - 1;
        }
        else
        {
            AdrLogCount = i - 1;
        }
    }
    else
    {
        AdrLogCount = 0;
        RamLoggerCount[0] = 0;
        W25QXX_Write_NoCheck(&RamLoggerCount[AdrLogCount],FLASH_LOG_COUNT_ADR + AdrLogCount,1);
    }
}

void LoggerOneItmPack(uint8_t	*pos, uint8_t *group, uint8_t *item, float value, uint8_t *typ, int32_t open, uint32_t vshort, uint8_t *result)
{
    uint8_t		i,j,k,m;
    uint16_t	adr = ONE_ITM_LOG_LENGHT * AdrRamLog;
    uint8_t 	*pdata8;

    if(CmpStr(pos,(unsigned char*)"LR",2))															//0th byte:pos
    {
        RamLogger[adr] = 0;
    }
    else if(CmpStr(pos,(unsigned char*)"LF",2))
    {
        RamLogger[adr] = 1;
    }
    else if(CmpStr(pos,(unsigned char*)"RF",2))
    {
        RamLogger[adr] = 2;
    }
    else if(CmpStr(pos,(unsigned char*)"RR",2))
    {
        RamLogger[adr] = 3;
    }
    else if(CmpStr(pos,(unsigned char*)"Left",4))
    {
        RamLogger[adr] = 4;
    }
    else if(CmpStr(pos,(unsigned char*)"Right",5))
    {
        RamLogger[adr] = 5;
    }
    else if(CmpStr(pos,(unsigned char*)"NA",2))
    {
        RamLogger[adr] = 6;
    }
    else if(CmpStr(pos,(unsigned char*)"C1_LR",5))															//0th byte:pos
    {
        RamLogger[adr] = 7;
    }
    else if(CmpStr(pos,(unsigned char*)"C1_LF",5))
    {
        RamLogger[adr] = 8;
    }
    else if(CmpStr(pos,(unsigned char*)"C1_RF",5))
    {
        RamLogger[adr] = 9;
    }
    else if(CmpStr(pos,(unsigned char*)"C1_RR",5))
    {
        RamLogger[adr] = 10;
    }
    else if(CmpStr(pos,(unsigned char*)"C2_LR",5))															//0th byte:pos
    {
        RamLogger[adr] = 11;
    }
    else if(CmpStr(pos,(unsigned char*)"C2_LF",5))
    {
        RamLogger[adr] = 12;
    }
    else if(CmpStr(pos,(unsigned char*)"C2_RF",5))
    {
        RamLogger[adr] = 13;
    }
    else if(CmpStr(pos,(unsigned char*)"C2_RR",5))
    {
        RamLogger[adr] = 14;
    }
    else if(CmpStr(pos,(unsigned char*)"C3_LR",5))															//0th byte:pos
    {
        RamLogger[adr] = 15;
    }
    else if(CmpStr(pos,(unsigned char*)"C3_LF",5))
    {
        RamLogger[adr] = 16;
    }
    else if(CmpStr(pos,(unsigned char*)"C3_RF",5))
    {
        RamLogger[adr] = 17;
    }
    else if(CmpStr(pos,(unsigned char*)"C3_RR",5))
    {
        RamLogger[adr] = 18;
    }
    else if(CmpStr(pos,(unsigned char*)"USBC10",6))
    {
        RamLogger[adr] = 29;
    }
    else if(CmpStr(pos,(unsigned char*)"USBC11",6))
    {
        RamLogger[adr] = 30;
    }
    else if(CmpStr(pos,(unsigned char*)"USBC12",6))
    {
        RamLogger[adr] = 31;
    }
    else if(CmpStr(pos,(unsigned char*)"USBC13",6))
    {
        RamLogger[adr] = 32;
    }
    else if(CmpStr(pos,(unsigned char*)"USBC14",6))
    {
        RamLogger[adr] = 33;
    }
    else if(CmpStr(pos,(unsigned char*)"USBC15",6))
    {
        RamLogger[adr] = 34;
    }
    else if(CmpStr(pos,(unsigned char*)"USBC0",5))
    {
        RamLogger[adr] = 19;
    }
    else if(CmpStr(pos,(unsigned char*)"USBC1",5))
    {
        RamLogger[adr] = 20;
    }
    else if(CmpStr(pos,(unsigned char*)"USBC2",5))
    {
        RamLogger[adr] = 21;
    }
    else if(CmpStr(pos,(unsigned char*)"USBC3",5))
    {
        RamLogger[adr] = 22;
    }
    else if(CmpStr(pos,(unsigned char*)"USBC4",5))
    {
        RamLogger[adr] = 23;
    }
    else if(CmpStr(pos,(unsigned char*)"USBC5",5))
    {
        RamLogger[adr] = 24;
    }
    else if(CmpStr(pos,(unsigned char*)"USBC6",5))
    {
        RamLogger[adr] = 25;
    }
    else if(CmpStr(pos,(unsigned char*)"USBC7",5))
    {
        RamLogger[adr] = 26;
    }
    else if(CmpStr(pos,(unsigned char*)"USBC8",5))
    {
        RamLogger[adr] = 27;
    }
    else if(CmpStr(pos,(unsigned char*)"USBC9",5))
    {
        RamLogger[adr] = 28;
    }

    if(CmpStr(group,(unsigned char*)"adj",3))													//1th byte:group
    {
        RamLogger[adr + 1] = 0;
    }
    else if(CmpStr(group,(unsigned char*)"gnd",3))
    {
        RamLogger[adr + 1] = 1;
    }
    else if(CmpStr(group,(unsigned char*)"Vbus",4))
    {
        RamLogger[adr + 1] = 2;
    }

    for( i = 0; i < 7 ; i++)													//2th~8th byte:item name
    {
        RamLogger[adr + 2 + i] = *(item + i);
    }

    pdata8=(uint8_t *)&value;													//9th~12th byte:value
    for(j=0; j<4; j++)
    {
        RamLogger[adr + 2 + i + j]=pdata8[j];
    }

    if(CmpStr(typ,(unsigned char*)"res",3))														//13th byte:type
    {
        RamLogger[adr + 2 + i + j] = 0;
    }
    else if(CmpStr(typ,(unsigned char*)"vdrp",4))
    {
        RamLogger[adr + 2 + i + j] = 1;
    }
    else if(CmpStr(typ,(unsigned char*)"cap",3))
    {
        RamLogger[adr + 2 + i + j] = 2;
    }
    else if(CmpStr(typ,(unsigned char*)"dds",3))
    {
        RamLogger[adr + 2 + i + j] = 3;
    }
    else if(CmpStr(typ,(unsigned char*)"TR",2))
    {
        RamLogger[adr + 2 + i + j] = 4;
    }
    else if(CmpStr(typ,(unsigned char*)"cap2",4))
    {
        RamLogger[adr + 2 + i + j] = 5;
    }

    pdata8=(uint8_t *)&open;													//14th~17th byte:open lim
    for(k = 0; k < 4; k++)
    {
        RamLogger[adr + 3 + i + j + k] = pdata8[k];
    }

    pdata8=(uint8_t *)&vshort;												//18th~21th byte:short lim
    for(m = 0; m < 4; m++)
    {
        RamLogger[adr + 3 + i + j + k + m] = pdata8[m];
    }

    if(CmpStr(result,(unsigned char*)"Pass",3))												//22th byte:result
    {
        RamLogger[adr + 3 + i + j + k + m] = 0;
    }
    else if(CmpStr(result,(unsigned char*)"Short",4))
    {
        RamLogger[adr + 3 + i + j + k + m] = 1;
    }
    else if(CmpStr(result,(unsigned char*)"Open",3))
    {
        RamLogger[adr + 3 + i + j + k + m] = 2;
    }
    else if(CmpStr(result,(unsigned char*)"Skip",3))
    {
        RamLogger[adr + 3 + i + j + k + m] = 3;
    }

    AdrRamLog++;
}

void WriteLoggerToW25QXX(void)
{
    uint16_t	adr_log_count, i=0;
    RTC_DateTypeDef sdatestructure;
    RTC_TimeTypeDef stimestructure;
    uint8_t					tmp;

    HAL_RTC_GetTime(&hrtc, &stimestructure, RTC_FORMAT_BIN);
    HAL_RTC_GetDate(&hrtc, &sdatestructure, RTC_FORMAT_BIN);
    sprintf((char *)StrTmp,"%d/%02d/%02d-%d-%02d:%02d:%02d\n",2000+sdatestructure.Year,sdatestructure.Month,sdatestructure.Date,sdatestructure.WeekDay,stimestructure.Hours,stimestructure.Minutes,stimestructure.Seconds);

    while(StrTmp[i] != '\n')																													//write date to ram
    {
        RamLogger[W25QXX_SECTOR_LENGTH - 31 + i] = StrTmp[i];
        i++;
    }
    RamLogger[W25QXX_SECTOR_LENGTH - 31 + i] = '\0';
    RamLogger[W25QXX_SECTOR_LENGTH - 1] = AdrRamLog;																	//write items_num of once testing to ram

    if(AdrLogCount < (W25QXX_SECTOR_LENGTH -1))																				//get next adr of count reg
    {
        adr_log_count = AdrLogCount + 1;
        tmp = RamLoggerCount[AdrLogCount];
    }
    else																																							//again,need erase the sector
    {
        adr_log_count = 0;
        tmp = RamLoggerCount[AdrLogCount];
        W25QXX_Erase_Sector(FLASH_LOG_COUNT_ADR/W25QXX_SECTOR_LENGTH);
        for(i = 0; i< W25QXX_SECTOR_LENGTH; i++)
        {
            RamLoggerCount[i] = 0xff;
        }
    }
    RamLoggerCount[adr_log_count] = tmp;
    AdrLogCount = adr_log_count;

    if(RamLoggerCount[AdrLogCount] < LOGGER_LENGTH)																	//add the count reg by 1      1~100
    {
        RamLoggerCount[AdrLogCount]++;
    }
    else
    {
        RamLoggerCount[AdrLogCount] = 1;
        if(Readu32DatFrom_FlashMCUReg(FLASH_LOG_LESS_100) != LogLengthIdx)							//if the logger count is larger than 100,the idx is set to 0x55555555
        {
            Writeu32DatTo_FlashMCUReg(&LogLengthIdx,1,FLASH_LOG_LESS_100);
        }
    }

//	sprintf(StrTmp,"adr=%x  AdrLogCount=%d \n%d\n",FLASH_LOG_COUNT_ADR + AdrLogCount,AdrLogCount,RamLoggerCount[AdrLogCount]);
//	UartPushTxBuffer(StrTmp);
//	UsartSendStart();
    W25QXX_Write_NoCheck(&RamLoggerCount[AdrLogCount],FLASH_LOG_COUNT_ADR + AdrLogCount,1);																							//write the latest count to the new flash reg

//	W25QXX_Read(RamLoggerCount,FLASH_LOG_COUNT_ADR,W25QXX_SECTOR_LENGTH);
//	sprintf(StrTmp,"%d %d\n",RamLoggerCount[0],RamLoggerCount[1]);
//	UartPushTxBuffer(StrTmp);
//	UsartSendStart();

    W25QXX_Download(RamLogger, FLASH_LOG_INI_ADR + (RamLoggerCount[AdrLogCount] - 1)*W25QXX_SECTOR_LENGTH, W25QXX_SECTOR_LENGTH); 				//write the testing logger to the next sector

    AdrRamLog = 0;
}

void LoggerOneItmUnPack(uint8_t	*buf)
{
    uint8_t		i;
    uint8_t		pos[8]= {'\0'};
    uint8_t		group[8]= {'\0'};
    uint8_t		item[8]= {'\0'};
    uint8_t		typ[8]= {'\0'};
    uint8_t		result[8]= {'\0'};
    float 		value;
    int32_t 	open;
    uint32_t 	vshort;

    switch(buf[0])
    {
    case 0:
        sprintf((char*)pos, "%s", "LR");
        break;
    case 1:
        sprintf((char*)pos, "%s", "LF");
        break;
    case 2:
        sprintf((char*)pos, "%s", "RF");
        break;
    case 3:
        sprintf((char*)pos, "%s", "RR");
        break;
    case 4:
        sprintf((char*)pos, "%s", "Left");
        break;
    case 5:
        sprintf((char*)pos, "%s", "Right");
        break;
    case 7:
        sprintf((char*)pos, "%s", "C1_LR");
        break;
    case 8:
        sprintf((char*)pos, "%s", "C1_LF");
        break;
    case 9:
        sprintf((char*)pos, "%s", "C1_RF");
        break;
    case 10:
        sprintf((char*)pos, "%s", "C1_RR");
        break;
    case 11:
        sprintf((char*)pos, "%s", "C2_LR");
        break;
    case 12:
        sprintf((char*)pos, "%s", "C2_LF");
        break;
    case 13:
        sprintf((char*)pos, "%s", "C2_RF");
        break;
    case 14:
        sprintf((char*)pos, "%s", "C2_RR");
        break;
    case 15:
        sprintf((char*)pos, "%s", "C3_LR");
        break;
    case 16:
        sprintf((char*)pos, "%s", "C3_LF");
        break;
    case 17:
        sprintf((char*)pos, "%s", "C3_RF");
        break;
    case 18:
        sprintf((char*)pos, "%s", "C3_RR");
        break;
    default:
        sprintf((char*)pos, "%s", "NA");
        break;
    }

    switch(buf[1])
    {
    case 0:
        sprintf((char*)group, "%s", "adj");
        break;
    case 1:
        sprintf((char*)group, "%s", "gnd");
        break;
    case 2:
        sprintf((char*)group, "%s", "Vbus");
        break;
    }

    for( i = 0; i < 7 ; i++)
    {
        item[i] = buf[2 + i];
    }

    value = *(float *)(buf+ 2 + i);

    switch(buf[6 + i])
    {
    case 0:
        sprintf((char*)typ, "%s", "res");
        break;
    case 1:
        sprintf((char*)typ, "%s", "vdrp");
        break;
    case 2:
        sprintf((char*)typ, "%s", "cap");
        break;
    case 3:
        sprintf((char*)typ, "%s", "dds");
        break;
    case 4:
        sprintf((char*)typ, "%s", "TR");
        break;
    case 5:
        sprintf((char*)typ, "%s", "cap2");
        break;
    }

    open = *(int32_t *)(buf+ 7 + i);
    vshort = *(uint32_t *)(buf+ 11 + i);

    switch(buf[15 + i])
    {
    case 0:
        sprintf((char*)result, "%s", "Pass");
        break;
    case 1:
        sprintf((char*)result, "%s", "Short");
        break;
    case 2:
        sprintf((char*)result, "%s", "Open");
        break;
    default:
        sprintf((char*)result, "%s", "Skip");
        break;
    }

    if(buf[6 + i] != 4)
    {
        sprintf((char*)StrTmp,"{\"pos\": \"%s\", \"group\": \"%s\", \"item\": \"%s\", \"value\": %2.2f, \"typ\": \"%s\", \"lim\": {\"open\": %d, \"short\": %d}, \"result\": \"%s\"}\r\n",
                pos,
                group,
                item,
                value,
                typ,
                open,
                vshort,
                result
               );
    }
    else
    {
        sprintf((char*)StrTmp,"{\"pos\": \"%s\", \"group\": \"%s\", \"item\": \"%s\", \"value\": %2.0f, \"typ\": \"%s\", \"lim\": {\"open\": %d, \"short\": %d}, \"result\": \"%s\"}\r\n",
                pos,
                group,
                item,
                value,
                typ,
                open,
                vshort,
                result
               );
    }
    UartPushTxBuffer(StrTmp);
    UsartSendStart();
}

static	uint8_t		dat_str[DATE_LENGTH]= {'\0'};
static	uint8_t		buf[ONE_ITM_LOG_LENGHT];

void funReadLogger(uint8_t ini,uint8_t logger_num)
{   //ini:1~100
    uint8_t		i,j;
    uint8_t		itm_num;

    if(ini)
    {
        if((ini + logger_num -1) > LOGGER_LENGTH)
        {
            return;
        }
        else
        {
            for(i = 0; i < logger_num; i++)
            {
                W25QXX_Read(dat_str,FLASH_LOG_INI_ADR + (ini + i) * W25QXX_SECTOR_LENGTH - 31,DATE_LENGTH);
                UartPushTxBuffer(dat_str);
                UartPushTxBuffer("\n");
                UsartSendStart();
                W25QXX_Read(&itm_num,FLASH_LOG_INI_ADR + (ini + i) * W25QXX_SECTOR_LENGTH - 1,1);
                for(j = 0; j < itm_num; j++)
                {
                    W25QXX_Read(buf,FLASH_LOG_INI_ADR + (ini + i - 1) * W25QXX_SECTOR_LENGTH + ONE_ITM_LOG_LENGHT * j,ONE_ITM_LOG_LENGHT);
                    LoggerOneItmUnPack(buf);
                }
            }
        }
    }
}

void ReadLoggerFromW25QXX(uint8_t logger_num)
{
    uint8_t		tmp_logger_num;

    if(Readu32DatFrom_FlashMCUReg(FLASH_LOG_LESS_100) != LogLengthIdx)
    {
        if(RamLoggerCount[AdrLogCount] == 0)
        {
            UartPushTxBuffer("no log\n");
            UsartSendStart();
            return;
        }
        else
        {
            if(RamLoggerCount[AdrLogCount] < logger_num)
            {
                tmp_logger_num = RamLoggerCount[AdrLogCount];
            }
            else
            {
                tmp_logger_num = logger_num;
            }
            //funReadLogger(1,tmp_logger_num);
            funReadLogger(RamLoggerCount[AdrLogCount] + 1 - tmp_logger_num,tmp_logger_num);
        }
    }
    else
    {
        if(LOGGER_LENGTH < logger_num)
        {
            tmp_logger_num = LOGGER_LENGTH;
        }
        else
        {
            tmp_logger_num = logger_num;
        }

//		if(tmp_logger_num <= (LOGGER_LENGTH - RamLoggerCount[AdrLogCount]))
//		{
//			funReadLogger(RamLoggerCount[AdrLogCount] + 1,tmp_logger_num);
//		}
//		else
//		{
//			funReadLogger(RamLoggerCount[AdrLogCount] + 1,LOGGER_LENGTH - RamLoggerCount[AdrLogCount]);
//			funReadLogger(1,tmp_logger_num - (LOGGER_LENGTH - RamLoggerCount[AdrLogCount]));
//		}

        if(tmp_logger_num <= RamLoggerCount[AdrLogCount])
        {
            funReadLogger(RamLoggerCount[AdrLogCount] + 1 - tmp_logger_num,tmp_logger_num);
        }
        else
        {
            funReadLogger(LOGGER_LENGTH + 1 - (tmp_logger_num - RamLoggerCount[AdrLogCount]),tmp_logger_num - RamLoggerCount[AdrLogCount]);	//first early
            funReadLogger(1,RamLoggerCount[AdrLogCount]);																																										//then upper
        }
    }
}

void ClearLogger(void)
{
    uint16_t	i;
    uint32_t	log_length_idx = 0xaaaaaaaa;

    W25QXX_Erase_Sector(FLASH_LOG_COUNT_ADR/W25QXX_SECTOR_LENGTH);
    for(i = 0; i< W25QXX_SECTOR_LENGTH; i++)
    {
        RamLoggerCount[i] = 0xff;
    }
    AdrLogCount = 0;
    RamLoggerCount[0] = 0;
    W25QXX_Write_NoCheck(&RamLoggerCount[AdrLogCount],FLASH_LOG_COUNT_ADR + AdrLogCount,1);
    Writeu32DatTo_FlashMCUReg(&log_length_idx,1,FLASH_LOG_LESS_100);
}
